
/****************************************************************************/

int kernelWindowDraw(objectKey key)
{
	return kernelWindowDrawClip(key, 0, 0, INT_MAX, INT_MAX);
}

/****************************************************************************/

int kernelWindowDrawClip(objectKey key, int xCoord, int yCoord, int width, int height)
{
	int status = 0;

	if (!initialized)
		return (status = ERR_NOTINITIALIZED);

	ACQUIRE_WINDOW_LIST
		return (status = ERR_NOLOCK);

	kernelWindow *window = castKeyToWindow(key);

	if (!window)
		status = ERR_NOSUCHENTRY;
	else if (!window->_drawClip)
		status = ERR_NOTIMPLEMENTED;
	else
		status = window->_drawClip(window, xCoord, yCoord, width, height);

	RELEASE_WINDOW_LIST

	return (status);
}

/****************************************************************************/

void kernelWindowDrawAll(void)
{
	// This function will redraw all windows.  Useful for example when the user
	// has changed the color scheme

	kernelWindow *window = NULL;
	int count;

	// Make sure we've been initialized
	if (!initialized)
		return;

	// Lock the window list
	ACQUIRE_WINDOW_LIST
		return;

	// Loop through the window list, looking for any visible ones that
	// intersect this area
	for (count = 0; count < numberWindows; count ++)
	{
		window = windowList[count];

		if (window->flags & WINFLAG_VISIBLE)
			kernelWindowDraw(window);
	}

	RELEASE_WINDOW_LIST

	kernelMouseDraw();

	return;
}

/****************************************************************************/

void kernelWindowRedrawArea(int xCoord, int yCoord, int width, int height)
{
	// This function will redraw an arbitrary area of the screen.  Initially
	// written to allow the mouse functions to erase the mouse without
	// having to know what's under it.  Could be useful for other things as
	// well.

	kernelWindow *window = NULL;
	screenArea area;
	screenArea intersectingArea;
	int count;

	// Make sure we've been initialized
	if (!initialized)
		return;

	ACQUIRE_WINDOW_LIST
		return; 

	// Don't do off the screen
	xCoord = max(0, xCoord);
	yCoord = max(0, yCoord);
	if ((xCoord + width) > screenWidth)
		width = (screenWidth - xCoord);
	if ((yCoord + height) > screenHeight)
		height = (screenHeight - yCoord);

	// If the root window has not yet been shown, clear the area first
	if ((rootWindow == NULL) || !(rootWindow->flags & WINFLAG_VISIBLE))
		kernelGraphicClearArea(NULL, &kernelDefaultDesktop, xCoord, yCoord, width, height);

	area.leftX = xCoord;
	area.topY = yCoord;
	area.rightX = (xCoord + (width - 1));
	area.bottomY = (yCoord + (height - 1));

	// Loop through the window list, looking for any visible ones that
	// intersect this area
	for (count = 0; count < numberWindows; count ++)
	{
		window = windowList[count];

		if ((window->flags & WINFLAG_VISIBLE) && doAreasIntersect(&area, makeWindowScreenArea(window)))
		{
			getIntersectingArea(makeWindowScreenArea(window), &area, &intersectingArea);
			intersectingArea.leftX   -= window->xCoord;
			intersectingArea.topY    -= window->yCoord;
			intersectingArea.rightX  -= window->xCoord;
			intersectingArea.bottomY -= window->yCoord;
			renderVisiblePortions(window, &intersectingArea, 0);
		}
	}

	// If there's an active menu that intersects this area, draw the relevent
	// part of that too, since they have buffers that are separate from their
	// windows' buffers
	if (activeMenu && (activeMenu->flags & WINFLAG_VISIBLE) &&
	    doAreasIntersect(&area, makeComponentScreenArea(activeMenu)))
	{
		window = activeMenu->window;

		getIntersectingArea(makeComponentScreenArea(activeMenu), &area, &intersectingArea);
		intersectingArea.leftX   -= (window->xCoord + activeMenu->xCoord);
		intersectingArea.topY    -= (window->yCoord + activeMenu->yCoord);
		intersectingArea.rightX  -= (window->xCoord + activeMenu->xCoord);
		intersectingArea.bottomY -= (window->yCoord + activeMenu->yCoord);

		kernelGraphicRenderBuffer(
			activeMenu->buffer,
			(window->xCoord + activeMenu->xCoord),
			(window->yCoord + activeMenu->yCoord),
			intersectingArea.leftX,
			intersectingArea.topY,
			(intersectingArea.rightX  - intersectingArea.leftX + 1),
			(intersectingArea.bottomY - intersectingArea.topY  + 1));
	}

	RELEASE_WINDOW_LIST

	return;
}

/****************************************************************************/

